﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using System.Xml;

namespace DownRepo
{
    public partial class main : Form
    {
        List<FileClass> depoList = new List<FileClass>();
        List<FileClass> tempList = new List<FileClass>();
        string inputDirectory = "";
        string outputDirectory = "c:\\Repository\\";
        WebClient wc = new WebClient();
        int counter = 0;

        public main()
        {
            InitializeComponent();
            wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
            wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
        }

        private void main_Load(object sender, EventArgs e)
        {
            txtOutputDirectory.Text = outputDirectory;

            listViewFiles.Columns.Add("");
            listViewFiles.Columns.Add("#");
            listViewFiles.Columns.Add("Name");
            listViewFiles.Columns.Add("Path");
        }

        private void btnGet_Click(object sender, EventArgs e)
        {
            inputDirectory = txtFtpAddress.Text;
            if (!inputDirectory.EndsWith("/"))
                inputDirectory += "/";
            depoList.Clear();
            readFromFTPServer();
        }

        private string GetDirectoryListingRegexForUrl(string url)
        {
            if (url.Equals(inputDirectory))
            {
                return "<a href=\".*\">(?<name>.*)</a>";
            }
            throw new NotSupportedException();
        }

        private void readFromFTPServer()
        {
            if (inputDirectory.StartsWith("ftp://"))
            {
                try
                {
                    FtpWebRequest ftpReq = (FtpWebRequest)FtpWebRequest.Create(inputDirectory);

                    ftpReq.Method = WebRequestMethods.Ftp.ListDirectory;
                    ftpReq.Credentials = new NetworkCredential("anonymous", "anonymous");
                    ftpReq.UsePassive = true;
                    ftpReq.UseBinary = true;
                    ftpReq.KeepAlive = false;

                    FtpWebResponse ftpRes = (FtpWebResponse)ftpReq.GetResponse();
                    Stream responseStream = ftpRes.GetResponseStream();
                    StreamReader reader = new StreamReader(responseStream);
                    int count = 0;
                    while (!reader.EndOfStream)
                    {
                        Application.DoEvents();
                        string temp = reader.ReadLine();
                        depoList.Add(new FileClass(count++, temp, inputDirectory + temp));
                    }

                    reader.Close();
                    responseStream.Close();
                    ftpRes.Close();

                    foreach (FileClass item in depoList)
                    {
                        ListViewItem lvi = new ListViewItem();
                        lvi.Text = "";
                        lvi.SubItems.Add(item.Id.ToString());
                        lvi.SubItems.Add(item.Name);
                        lvi.SubItems.Add(item.Path);
                        lvi.Tag = item;
                        listViewFiles.Items.Add(lvi);
                    }
                    listViewFiles.Columns[0].Width = -1;
                    listViewFiles.Columns[1].Width = -1;
                    listViewFiles.Columns[2].Width = -1;
                    listViewFiles.Columns[3].Width = -1;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("There was an error connecting to the FTP Server.\nError message is: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else if (inputDirectory.StartsWith("http://"))
            {
                try
                {
                    HttpWebRequest httpReq = (HttpWebRequest)HttpWebRequest.Create(inputDirectory);
                    httpReq.Credentials = new NetworkCredential("anonymous", "");
                    httpReq.KeepAlive = false;

                    HttpWebResponse httpRes = (HttpWebResponse)httpReq.GetResponse();
                    Stream responseStream = httpRes.GetResponseStream();
                    StreamReader reader = new StreamReader(responseStream);

                    string html = reader.ReadToEnd();
                    Regex regex = new Regex(GetDirectoryListingRegexForUrl(inputDirectory));
                    MatchCollection matches = regex.Matches(html);
                    int count = 0;
                    if (matches.Count > 0)
                    {
                        foreach (Match match in matches)
                        {
                            if (match.Success)
                            {
                                depoList.Add(new FileClass(count++, match.Groups["name"].Value, inputDirectory + match.Groups["name"].Value));
                            }
                        }
                    }   

                    reader.Close();
                    responseStream.Close();
                    httpRes.Close();

                    foreach (FileClass item in depoList)
                    {
                        ListViewItem lvi = new ListViewItem();
                        lvi.Text = "";
                        lvi.SubItems.Add(item.Id.ToString());
                        lvi.SubItems.Add(item.Name);
                        lvi.SubItems.Add(item.Path);
                        lvi.Tag = item;
                        listViewFiles.Items.Add(lvi);
                    }
                    listViewFiles.Columns[0].Width = -1;
                    listViewFiles.Columns[1].Width = -1;
                    listViewFiles.Columns[2].Width = -1;
                    listViewFiles.Columns[3].Width = -1;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("There was an error connecting to the HTTP Server.\nError message is: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
                MessageBox.Show("Check the url has ftp:// or http:// prefix.");
        }

        private void btnSelect_Click(object sender, EventArgs e)
        {
            if (DialogResult.OK == folderBrowserDialog1.ShowDialog())
            {
                outputDirectory = folderBrowserDialog1.SelectedPath;
                if (!outputDirectory.EndsWith("\\"))
                    outputDirectory += "\\";
                txtOutputDirectory.Text = outputDirectory;            
            }
        }

        private void btnDown_Click(object sender, EventArgs e)
        {
            counter = 0;
            if (txtFtpAddress.Text != "" && txtOutputDirectory.Text != "" && listViewFiles.CheckedItems.Count > 0)
            {
                FileClass item = listViewFiles.CheckedItems[counter].Tag as FileClass;
                counter++;
                Uri myUri = new Uri(item.Path);
                wc.DownloadFileAsync(myUri, outputDirectory + item.Name);                
            }
        }

        void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            string filename = (listViewFiles.CheckedItems[counter - 1].Tag as FileClass).Name;
            textBox2.Text = String.Format("Downloading: ({0}/{1}): {2} .................. {3} | {4} B  {5} %", counter, listViewFiles.CheckedItems.Count, filename, e.BytesReceived, e.TotalBytesToReceive, e.ProgressPercentage) + Environment.NewLine;
            progressBar1.Value = e.ProgressPercentage;
        }

        void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (counter < listViewFiles.CheckedItems.Count)
            {
                FileClass item = listViewFiles.CheckedItems[counter].Tag as FileClass;
                counter++;
                Uri myUri = new Uri(item.Path);

                wc.DownloadFileAsync(myUri, outputDirectory + item.Name);
            }
            else
            {
                MessageBox.Show("All Downloads Completed");
            }
        }


        private void btnResume_Click(object sender, EventArgs e)
        {

            if (btnResume.Text == ">")
            {
                btnResume.Text = "||";
            }
            else
            {
                btnResume.Text = ">";
            }
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.CheckState == CheckState.Unchecked)
            {
                for (int i = 0; i < listViewFiles.Items.Count; i++)
                {
                    listViewFiles.Items[i].Checked = false;
                }
            }
            else
            {
                for (int i = 0; i < listViewFiles.Items.Count; i++)
                {
                    listViewFiles.Items[i].Checked = true;
                }
            }
        }

        private void txtSearch_TextChanged(object sender, EventArgs e)
        {
            
            listViewFiles.Items.Clear();


            tempList = depoList.FindAll(p => p.Name.ToLower().Contains(txtSearch.Text.ToLower()));
            foreach (FileClass item in tempList)
            {
                ListViewItem lvi = new ListViewItem();
                lvi.Text = "";
                lvi.SubItems.Add(item.Id.ToString());
                lvi.SubItems.Add(item.Name);
                lvi.SubItems.Add(item.Path);
                lvi.Tag = item;
                listViewFiles.Items.Add(lvi);
            }           
        }
    }
}
